<!DOCTYPE html>
<html class="client-nojs vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-0 vector-toc-not-available vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-0 skin-theme-clientpref-day vector-sticky-header-enabled" lang="de" dir="ltr"><head>
<meta charset="UTF-8">
<title>Message Passing Interface</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="./_res_/favicon.png">
<link rel="canonical" href="https://de.wikipedia.org/wiki/Message_Passing_Interface"> <link href="./_mw_/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.math.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.wikimediamessages.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link href="./_mw_/ext.gadget.citeRef.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.defaultPlainlinks.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonHide.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonLayout.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonStyle.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiDarkmode.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiResponsive.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.specialSearch.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="./_mw_/site.styles.css">
<link rel="stylesheet" type="text/css" href="./_mw_/noscript.css">
<link rel="stylesheet" type="text/css" href="./_res_/footer.css">
<link rel="stylesheet" type="text/css" href="./_res_/vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Message_Passing_Interface rootpage-Message_Passing_Interface skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading"><span class="mw-page-title-main">Message Passing Interface</span></h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="contentSub">
<div id="mw-content-subtitle"></div>
</div>
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="de" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="de" dir="ltr"><table class="float-right infobox toccolours toptextcells" style="border-spacing:5px; font-size:90%; text-align:left; width:21em;">
<tbody><tr>
<th colspan="2" class="hintergrundfarbe6" style="font-size:105%; text-align:center;">MPI
<p class="mw-empty-elt">
</p>
</th></tr>
<tr>
<td colspan="2" class="notheme" style="text-align:center; background-color:#f8f9fa;"><span class="mw-default-size" typeof="mw:File"></span>
</td></tr>
<tr>
<th colspan="2" class="hintergrundfarbe5" style="font-size:105%; text-align:center;">Basisdaten
<p class="mw-empty-elt">
</p>
</th></tr>
<tr>
<td><b><a href="Softwareentwickler" title="Softwareentwickler">Entwickler</a></b>
</td>
<td><a rel="nofollow" class="external text" href="http://www.mpi-forum.org/">MPI Forum</a>
</td></tr>
<tr>
<td><b>Aktuelle <a href="Version_(Software)" title="Version (Software)">Version</a></b>
</td>
<td><a rel="nofollow" class="external text" href="https://www.mpi-forum.org/docs/mpi-4.1/mpi41-report.pdf">Version 4.1</a> (PDF; 5,3 MB) <br> (2. November 2023)
</td></tr>
<tr>
<td><b><a href="Betriebssystem" title="Betriebssystem">Betriebssystem</a></b>
</td>
<td><a href="Linux" title="Linux">Linux</a>, <a href="Unix" title="Unix">Unix</a>, <a href="Microsoft_Windows_NT" title="Microsoft Windows NT">Microsoft Windows NT</a>, <a href="MacOS" title="MacOS">macOS</a>
</td></tr>
<tr>
<td><b><a href="Programmiersprache" title="Programmiersprache">Programmiersprache</a></b>
</td>
<td><a href="C%2B%2B" title="C++">C++</a>, <a href="C_(Programmiersprache)" title="C (Programmiersprache)">C</a>, <a href="Fortran" title="Fortran">Fortran</a>, <a href="Python_(Programmiersprache)" title="Python (Programmiersprache)">Python</a>, <a href="Java_(Programmiersprache)" title="Java (Programmiersprache)">Java</a>
</td></tr>
<tr>
<td><b>Kategorie</b>
</td>
<td><a href="Programmierschnittstelle" title="Programmierschnittstelle">API</a>
</td></tr>
<tr>
<td><b><a href="Lokalisierung_(Softwareentwicklung)" title="Lokalisierung (Softwareentwicklung)">deutschsprachig</a></b>
</td>
<td>nein
</td></tr>
<tr>
<td class="hintergrundfarbe5" colspan="2" style="text-align:center;"><a rel="nofollow" class="external text" href="http://www.mpi-forum.org/">www.mpi-forum.org</a>
</td></tr></tbody></table>
<p><b>Message Passing Interface</b> (<b>MPI</b>) ist ein Standard, der den <a href="Nachrichtenaustausch" title="Nachrichtenaustausch">Nachrichtenaustausch</a> bei parallelen Berechnungen auf verteilten Computersystemen beschreibt. Er legt dabei eine Sammlung von Operationen und ihre Semantik, also eine <a href="Programmierschnittstelle" title="Programmierschnittstelle">Programmierschnittstelle</a> fest, aber keine <a href="Implementierung" title="Implementierung">Implementierung</a>.
</p><p>Eine MPI-Applikation besteht in der Regel aus mehreren miteinander kommunizierenden <a href="Prozess_(Informatik)" title="Prozess (Informatik)">Prozessen</a>, die alle zu Beginn der Programmausführung parallel gestartet werden. Alle diese Prozesse arbeiten dann gemeinsam an einem Problem und nutzen zum Datenaustausch Nachrichten, welche explizit von einem zum anderen Prozess geschickt werden. Ein Vorteil dieses Prinzips ist es, dass der Nachrichtenaustausch auch über Rechnergrenzen hinweg funktioniert. Parallele MPI-Programme sind somit sowohl auf PC-<a href="Computercluster" class="mw-redirect" title="Computercluster">Clustern</a> (hier funktioniert der Austausch der Nachrichten z. B. über <a href="Transmission_Control_Protocol" title="Transmission Control Protocol">TCP</a>), als auch auf dedizierten <a href="Parallelrechner" title="Parallelrechner">Parallelrechnern</a> ausführbar (hier läuft der Nachrichtenaustausch über ein Hochgeschwindigkeitsnetz wie <a href="InfiniBand" title="InfiniBand">InfiniBand</a> oder <a href="Myrinet" title="Myrinet">Myrinet</a> oder über den <a href="Shared_Memory" title="Shared Memory">gemeinsamen</a> <a href="Hauptspeicher" class="mw-redirect" title="Hauptspeicher">Hauptspeicher</a>).
</p>
<div class="mw-heading mw-heading2"><h2 id="Geschichte">Geschichte</h2></div>
<p>1992 begann die Entwicklung des MPI 1.0 Standards mit Entwürfen (November 1992, Februar 1993, November 1993). Ausgangspunkt waren ältere Kommunikationsbibliotheken wie PVM, PARMACS, P4, Chameleon und Zipcode. Der Standard erschien am 5. Mai 1994 mit
</p>
<ul><li>Punkt-zu-Punkt-Kommunikation</li>
<li>globale Kommunikation</li>
<li>Gruppen, Kontext und Kommunikatoren</li>
<li>Umgebung</li>
<li>Profiling-Schnittstelle</li>
<li>Spracheinbindung für C und <a href="Fortran" title="Fortran">Fortran</a> 77</li></ul>
<p>Im Juni 1995 erfolgten Fehlerkorrekturen mit MPI 1.1.
</p><p>Am 18. Juli 1997 wurde die stabile Version MPI 1.2 veröffentlicht, die neben weiteren Fehlerkorrekturen eine Versionidentifikation erlaubt. Sie wird auch als MPI-1 bezeichnet.
</p><p>Am 30. Mai 2008 erschien MPI 1.3 mit weiteren Fehlerkorrekturen und Klarstellungen.
</p><p>Zeitgleich zur Version 1.2 wurde am 18. Juli 1997 auch der MPI 2.0 Standard verabschiedet. Dieser wird auch als MPI-2 bezeichnet und enthält unter anderem folgende Erweiterungen:
</p>
<ul><li>parallele Datei-Ein-/Ausgabe</li>
<li>dynamische Prozessverwaltung</li>
<li>Zugriff auf Speicher anderer Prozesse</li>
<li>zusätzliche Spracheinbindung von <a href="C%2B%2B" title="C++">C++</a> und Fortran 90</li></ul>
<p>Am 23. Juni 2008 wurden die bisher separaten Teile MPI-1 und MPI-2 zu einem gemeinsamen Dokument vereint und als MPI 2.1 veröffentlicht. MPI Standard Version 2.2 ist vom 4. September 2009 und enthält weitere Verbesserungen und kleinere Erweiterungen.
</p><p>Am 21. September 2012 hat das MPI Forum MPI-3 veröffentlicht,<sup id="cite_ref-1" class="reference"><a href="#cite_note-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup> das neue Funktionalität einarbeitet wie beispielsweise nicht blockierende Kollektive, ein verbessertes einseitiges Kommunikationsmodell (RMA, Remote Memory Access), ein neues Fortran-Interface, topographiebezogene Kommunikation und nicht blockierende parallele Ein- und Ausgabe.<sup id="cite_ref-2" class="reference"><a href="#cite_note-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>
</p><p>Am 9. Juni 2021 wurde MPI-4 veröffentlicht. Wesentliche Neuerungen sind Funktionsinterfaces, die Parameter mit einem größeren Wertebereich unterstützen. Zuvor waren durch den vorgegebenen <a href="Integer_(Datentyp)#Häufige_Speicherformen" title="Integer (Datentyp)">32-bit Datentyp</a> wesentliche Größen, wie z. B. die Anzahl zu kommunizierender Datenelemente, auf etwas mehr als zwei Milliarden beschränkt. Persistente Kollektive eröffnen Möglichkeiten zur Optimierung wiederholt ausgeführter Kommunikation und sind zudem im Gegensatz zu den schon vorhandenen kollektiven Operationen in beliebiger Reihenfolge ausführbar. Zudem wurde die Fehlerbehandlung in vielen Punkten verbessert und ein neues Session-Modell zur dynamischen Nutzung der von MPI verwalteten Ressourcen eingeführt.<sup id="cite_ref-3" class="reference"><a href="#cite_note-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup>
</p><p>Zu den Hauptentwicklern gehört <a href="Bill_Gropp" title="Bill Gropp">Bill Gropp</a>.
</p>
<div class="mw-heading mw-heading2"><h2 id="Punkt-zu-Punkt_Kommunikation">Punkt-zu-Punkt Kommunikation</h2></div>
<p>Die grundlegendste Art der Kommunikation findet zwischen zwei Prozessen statt: ein Sendeprozess übermittelt dabei Informationen an einen Empfangsprozess. In MPI werden diese Informationen in sogenannte Nachrichten verpackt, die mit den Parametern <code>buffer</code>, <code>count</code>, und <code>datatype</code> beschrieben werden. Zu jeder Sendeoperation muss eine passende Empfangsoperation existieren. Da in parallelen Anwendungen die bloße Reihenfolge der Abarbeitung von Operationen nicht immer ausreichend ist, bietet MPI zusätzlich den <code>tag</code>-Parameter an – nur wenn dieser Wert bei Sende- und Empfangsoperation identisch ist, dann passen beide zusammen.
</p>
<div class="mw-heading mw-heading3"><h3 id="Blockierendes_Senden_und_Empfangen">Blockierendes Senden und Empfangen</h3></div>
<p>Die einfachsten Operationen für eine Punkt-zu-Punkt Kommunikation sind <i>senden</i> und <i>empfangen</i>:
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">MPI_Send</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Datatype</span><span class="w"> </span><span class="n">datatype</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">dest</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">tag</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Comm</span><span class="w"> </span><span class="n">comm</span><span class="p">)</span>
</pre></div>
<ul><li><i>buf</i>: <a href="Zeiger_(Informatik)" title="Zeiger (Informatik)">Zeiger</a> auf den Sendepuffer</li>
<li><i>count</i>: Zahl der Elemente im Sendepuffer</li>
<li><i>datatype</i>: <a href="Datentyp" title="Datentyp">Datentyp</a> der Elemente im Sendepuffer</li>
<li><i>dest</i>: Rang des Zielprozesses</li>
<li><i>tag</i>: Markierung der Nachricht</li>
<li><i>comm</i>: Kommunikator der Prozessgruppe</li></ul>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">MPI_Recv</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Datatype</span><span class="w"> </span><span class="n">datatype</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">source</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">tag</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Comm</span><span class="w"> </span><span class="n">comm</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Status</span><span class="o">*</span><span class="w"> </span><span class="n">status</span><span class="p">)</span>
</pre></div>
<ul><li><code>buf</code>: Zeiger auf einen Empfangspuffer ausreichender Größe</li>
<li><code>count</code>: Zahl der Elemente im Empfangspuffer</li>
<li><code>datatype</code>: Datentyp der Elemente im Empfangspuffer</li>
<li><code>source</code>: Rang des Quellprozesses (mit <code>source=MPI_ANY_SOURCE</code> wird von einem beliebigen Prozess empfangen)</li>
<li><code>tag</code>: erwartete Markierung der Nachricht (mit <code>tag=MPI_ANY_TAG</code> wird jede Nachricht empfangen)</li>
<li><code>comm</code>: Kommunikator der Prozessgruppe</li>
<li><code>status</code>: Zeiger auf eine Statusstruktur, in der Informationen über die empfangene Nachricht abgelegt werden sollen</li></ul>
<p>Die beiden Operationen sind <i>blockierend</i> und <i>asynchron</i>. Das bedeutet:
</p>
<ul><li><code>MPI_Recv</code> kann ausgeführt werden, bevor das zugehörige <code>MPI_Send</code> gestartet wurde</li>
<li><code>MPI_Recv</code> blockiert, bis die Nachricht vollständig empfangen wurde</li></ul>
<p>Analog gilt:
</p>
<ul><li><code>MPI_Send</code> kann ausgeführt werden, bevor das zugehörige <code>MPI_Recv</code> gestartet wurde</li>
<li><code>MPI_Send</code> blockiert, bis der Sendepuffer wiederverwendet werden kann (d. h. die Nachricht vollständig übermittelt oder zwischengepuffert wurde)</li></ul>
<div class="mw-heading mw-heading4"><h4 id="Programmbeispiel">Programmbeispiel</h4></div>
<p>Die Verwendung von <code>MPI_Send</code> und <code>MPI_Recv</code> wird im folgenden <a href="ANSI-C" class="mw-redirect" title="ANSI-C">ANSI-C</a>-Beispiel für 2 MPI-Prozesse veranschaulicht:
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">"mpi.h"</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><string.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">myrank</span><span class="p">,</span><span class="w"> </span><span class="n">message_size</span><span class="o">=</span><span class="mi">50</span><span class="p">,</span><span class="w"> </span><span class="n">tag</span><span class="o">=</span><span class="mi">42</span><span class="p">;</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">message</span><span class="p">[</span><span class="n">message_size</span><span class="p">];</span>
<span class="w"> </span><span class="n">MPI_Status</span><span class="w"> </span><span class="n">status</span><span class="p">;</span>
<span class="w"> </span><span class="n">MPI_Init</span><span class="p">(</span><span class="o">&</span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">argv</span><span class="p">);</span>
<span class="w"> </span><span class="n">MPI_Comm_rank</span><span class="p">(</span><span class="n">MPI_COMM_WORLD</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">myrank</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">myrank</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">MPI_Recv</span><span class="p">(</span><span class="n">message</span><span class="p">,</span><span class="w"> </span><span class="n">message_size</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_CHAR</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">tag</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_COMM_WORLD</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">status</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"received </span><span class="se">\"</span><span class="s">%s</span><span class="se">\"\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">message</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">strcpy</span><span class="p">(</span><span class="n">message</span><span class="p">,</span><span class="w"> </span><span class="s">"Hello, there"</span><span class="p">);</span>
<span class="w"> </span><span class="n">MPI_Send</span><span class="p">(</span><span class="n">message</span><span class="p">,</span><span class="w"> </span><span class="n">strlen</span><span class="p">(</span><span class="n">message</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_CHAR</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">tag</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_COMM_WORLD</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">MPI_Finalize</span><span class="p">();</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Nichtblockierende_Kommunikation">Nichtblockierende Kommunikation</h3></div>
<p>Die Effizienz einer parallelen Anwendung kann oftmals gesteigert werden, indem man Kommunikation mit Berechnung überlappt und/oder synchronisationsbedingte Wartezeiten vermeidet. Dazu definiert der MPI-Standard sogenannte nichtblockierende Kommunikation, bei der die Kommunikationsoperation lediglich angestoßen wird. Eine separate Funktion muss dann aufgerufen werden, um solch eine Operation zu beenden. Im Unterschied zur blockierenden Variante wird beim Starten der Operation ein <code>Request</code>-Objekt erzeugt, mit dessen Hilfe auf die Beendigung dieser Operation geprüft oder gewartet werden kann.
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">MPI_Isend</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Datatype</span><span class="w"> </span><span class="n">datatype</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">dest</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">tag</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Comm</span><span class="w"> </span><span class="n">comm</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Request</span><span class="o">*</span><span class="w"> </span><span class="n">request</span><span class="p">)</span>
</pre></div>
<ul><li>…</li>
<li><code>request</code>: Adresse der <a href="Datenstruktur" title="Datenstruktur">Datenstruktur</a>, die Informationen zur Operation enthält</li></ul>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">MPI_Irecv</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Datatype</span><span class="w"> </span><span class="n">datatype</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">source</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">tag</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Comm</span><span class="w"> </span><span class="n">comm</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Request</span><span class="o">*</span><span class="w"> </span><span class="n">request</span><span class="p">)</span>
</pre></div>
<ul><li>…</li></ul>
<div class="mw-heading mw-heading4"><h4 id="Fortschritt_abfragen">Fortschritt abfragen</h4></div>
<p>Um den Fortschritt einer dieser Operationen zu erfahren, wird folgende Operation verwendet:
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">MPI_Test</span><span class="w"> </span><span class="p">(</span><span class="n">MPI_Request</span><span class="o">*</span><span class="w"> </span><span class="n">request</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">*</span><span class="w"> </span><span class="n">flag</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Status</span><span class="o">*</span><span class="w"> </span><span class="n">status</span><span class="p">)</span>
</pre></div>
<p>Wobei <code>flag=1</code> oder <code>0</code> gesetzt wird, je nachdem, ob die Operation abgeschlossen ist oder noch andauert.
</p>
<div class="mw-heading mw-heading4"><h4 id="Blockierend_warten">Blockierend warten</h4></div>
<p>Um dennoch blockierend auf eine <code>MPI_Isend</code>- oder <code>MPI_Irecv</code>-Operation zu warten, wird folgende Operation benutzt:
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">MPI_Wait</span><span class="w"> </span><span class="p">(</span><span class="n">MPI_Request</span><span class="o">*</span><span class="w"> </span><span class="n">request</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Status</span><span class="o">*</span><span class="w"> </span><span class="n">status</span><span class="p">)</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Synchronisierendes_Senden">Synchronisierendes Senden</h3></div>
<p>Für die Sendeoperationen werden auch die synchronen Varianten <code>MPI_Ssend</code> und <code>MPI_Issend</code> definiert. In diesem Modus wird das Senden erst dann beendet, wenn die zugehörige Empfangsoperation begonnen wurde.
</p>
<div class="mw-heading mw-heading3"><h3 id="Puffernde_Varianten">Puffernde Varianten</h3></div>
<p>…
</p>
<div class="mw-heading mw-heading2"><h2 id="Gruppen_und_Kommunikatoren">Gruppen und Kommunikatoren</h2></div>
<p>Prozesse lassen sich in <i>Gruppen</i> zusammenfassen, wobei jedem Prozess eine eindeutige Nummer, der sogenannte <i>Rang</i> zugeordnet wird. Für den Zugriff auf eine Gruppe wird ein <i>Kommunikator</i> benötigt. Soll also eine globale Kommunikationsoperation auf eine Gruppe beschränkt werden, so muss der zur Gruppe gehörende Kommunikator angegeben werden. Der Kommunikator für die Menge aller Prozesse heißt <code>MPI_COMM_WORLD</code>.
</p><p>Die zum Kommunikator <code>comm</code> gehörende Gruppe erhält man mit
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="n">MPI_Comm_group</span><span class="w"> </span><span class="p">(</span><span class="n">MPI_Comm</span><span class="w"> </span><span class="n">comm</span><span class="p">,</span><span class="w"> </span><span class="n">MPI_Group</span><span class="o">*</span><span class="w"> </span><span class="n">group</span><span class="p">)</span>
</pre></div>
<p>Für Prozessgruppen stehen die üblichen Mengenoperationen zur Verfügung.
</p>
<div class="mw-heading mw-heading3"><h3 id="Vereinigung">Vereinigung</h3></div>
<p>Zwei Gruppen <code>group1</code> und <code>group2</code> können zu einer neuen Gruppe <code>new_group</code> vereinigt werden:
</p><p><code>
int <b>MPI_Group_union</b> (MPI_Group <i>group1</i>, MPI_Group <i>group2</i>, MPI_Group* <i>new_group</i>)
</code>
</p><p>Die Prozesse aus <code>group1</code> behalten ihre ursprüngliche Nummerierung. Die aus <code>group2</code>, die nicht bereits in der ersten enthalten sind, werden fortlaufend weiter nummeriert.
</p>
<div class="mw-heading mw-heading3"><h3 id="Schnittmenge">Schnittmenge</h3></div>
<p>Die Schnittmenge zweier Gruppen erhält man mit
</p><p><code>
int <b>MPI_Group_intersection</b> (MPI_Group <i>group1</i>, MPI_Group <i>group2</i>, MPI_Group* <i>new_group</i>)
</code>
</p>
<div class="mw-heading mw-heading3"><h3 id="Differenz">Differenz</h3></div>
<p>Die Differenz zweier Gruppen erhält man mit
</p><p><code>
int <b>MPI_Group_difference</b> (MPI_Group <i>group1</i>, MPI_Group <i>group2</i>, MPI_Group* <i>new_group</i>)
</code>
</p>
<div class="mw-heading mw-heading2"><h2 id="Globale_Kommunikation">Globale Kommunikation</h2></div>
<p>In parallelen Anwendungen trifft man häufig spezielle Kommunikationsmuster an, bei denen mehrere oder gar alle MPI-Prozesse gleichzeitig beteiligt sind. Der MPI-Standard hat deswegen für die wichtigsten Muster eigene Operationen definiert. Diese unterscheidet man grob in drei Arten: Synchronisation (Barrier), Kommunikation (z.Bsp. Broadcast, Gather, Alltoall) und Kommunikation gekoppelt mit Berechnung (z. B. Reduce oder Scan). Manche dieser Operationen verwenden einen ausgewählten MPI-Prozess, der eine Sonderrolle einnimmt und der typischerweise mit <code>root</code> bezeichnet wird. Wo es sinnvoll ist, existieren zusätzlich zu den regulären Kommunikationsoperationen noch vektorbasierte Varianten (z. B. Scatterv), die unterschiedliche Argumente pro Prozess ermöglichen.
</p>
<div class="mw-heading mw-heading3"><h3 id="Broadcast_(ausstrahlen)"><span id="Broadcast_.28ausstrahlen.29"></span>Broadcast (ausstrahlen)</h3></div>
<p>Mit der <i>Broadcast</i>-Operation schickt ein ausgewählter MPI-Prozess <code>root</code> allen anderen Prozessen in seiner Gruppe <code>comm</code> die gleichen Daten.
Die dafür definierte Funktion ist dabei für alle beteiligten Prozesse identisch:
</p><p><code>
int <b>MPI_Bcast</b> (void *<i>buffer</i>, int <i>count</i>, MPI_Datatype <i>type</i>, int <i>root</i>, MPI_Comm <i>comm</i>)
</code>
</p><p>Der MPI-Prozess <code>root</code> stellt in <code>buffer</code> seine Daten zur Verfügung, während die anderen Prozesse hier die Adresse ihres Empfangspuffers übergeben. Die restlichen Parameter müssen bei allen Prozessen gleich (bzw. gleichwertig) sein. Nachdem die Funktion zurückkehrt, befinden sich in allen Puffern die Daten, die ursprünglich nur bei <code>root</code> vorhanden waren.
</p>
<div class="mw-heading mw-heading3"><h3 id="Gather_(sammeln)"><span id="Gather_.28sammeln.29"></span>Gather (sammeln)</h3></div>
<p>Mit der <i>Gather</i>-Operation sammelt der MPI-Prozess <code>root</code> die Daten aller beteiligten Prozesse ein. Die Daten aller Sendepuffer werden dabei (nach Rang sortiert) hintereinander im Empfangspuffer abgelegt:
</p><p><code>
int <b>MPI_Gather</b> (void *<i>sendbuf</i>, int <i>sendcount</i>, MPI_Datatype <i>sendtype</i>, void *<i>recvbuf</i>, int <i>recvcount</i>, MPI_Datatype <i>recvtype</i>, int <i>root</i>, MPI_Comm <i>comm</i>)
</code>
</p>
<div class="mw-heading mw-heading4"><h4 id="Vektorbasierte_Variante">Vektorbasierte Variante</h4></div>
<p>Die vektorbasierte Variante der Gather-Operation erlaubt eine prozessabhängige Anzahl von Elementen:
</p><p><code>
int <b>MPI_Gatherv</b> (void *<i>sendbuf</i>, int <i>sendcount</i>, MPI_Datatype <i>sendtype</i>, void *<i>recvbuf</i>, int *<i>recvcounts</i>, int *<i>displs</i>, MPI_Datatype <i>recvtype</i>, int <i>root</i>, MPI_Comm <i>comm</i>)
</code>
</p>
<ul><li><code>recvcounts</code>: Feld, das die Zahl der Elemente enthält, die von den einzelnen Prozessen empfangen werden (nur für <code>root</code> relevant)</li>
<li><code>displs</code>: Feld, dessen Eintrag i die Verschiebung im Empfangspuffer festlegt, bei der die Daten von Prozess i abgelegt werden sollen (ebenfalls nur für <code>root</code> relevant)</li></ul>
<p>Bei den Feldern ist zu beachten, dass im Empfangspuffer zwar Lücken erlaubt sind aber keine Überlappungen.
Sollen also etwa von 3 Prozessen jeweils 1, 2 und 3 Elemente vom Typ <i>Integer</i> empfangen werden, so muss <code>recvcounts = {1, 2, 3}</code> und <code>displs = {0, 1 * sizeof(int), 3 * sizeof(int)}</code> gesetzt werden.
</p>
<div class="mw-heading mw-heading3"><h3 id="Scatter_(streuen)"><span id="Scatter_.28streuen.29"></span>Scatter (streuen)</h3></div>
<p>Mit einer <i>Scatter</i>-Operation schickt der MPI Prozess <code>root</code> jedem beteiligten Prozess ein unterschiedliches, aber gleich großes Datenelement:
</p><p><code>int <b>MPI_Scatter</b> (void *<i>sendbuf</i>, int <i>sendcount</i>, MPI_Datatype <i>sendtype</i>, void *<i>recvbuf</i>, int <i>recvcount</i>, MPI_Datatype <i>recvtype</i>, int <i>root</i>, MPI_Comm <i>comm</i>)</code>
</p>
<div class="mw-heading mw-heading4"><h4 id="Vektorbasierte_Variante_2">Vektorbasierte Variante</h4></div>
<p><code>int <b>MPI_Scatterv</b> (void *<i>sendbuf</i>, int *<i>sendcounts</i>, int *<i>displs</i>, MPI_Datatype <i>sendtype</i>, void *<i>recvbuf</i>, int <i>recvcount</i>, MPI_Datatype <i>recvtype</i>, int <i>root</i>, MPI_Comm <i>comm</i>)</code>
</p>
<div class="mw-heading mw-heading3"><h3 id="Akkumulation">Akkumulation</h3></div>
<p>Die Akkumulation ist eine spezielle Form der <i>Gather</i>-Operation. Hierbei werden ebenfalls die Daten aller beteiligten Prozesse aufgesammelt, aber zusätzlich noch mittels einer festgelegten Reduktionsoperation zu einem Datum reduziert. Sei beispielsweise <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle x_{i}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msub>
<mi>x</mi>
<mrow class="MJX-TeXAtom-ORD">
<mi>i</mi>
</mrow>
</msub>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle x_{i}}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/e87000dd6142b81d041896a30fe58f0c3acb2158.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.671ex; width:2.129ex; height:2.009ex;" alt="{\displaystyle x_{i}}" loading="lazy"></span> der Wert bei dem Prozess mit Rang <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle i}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>i</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle i}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/add78d8608ad86e54951b8c8bd6c8d8416533d20.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:0.802ex; height:2.176ex;" alt="{\displaystyle i}" loading="lazy"></span>, dann liefert Reduce(+) die Gesamtsumme aller Werte: <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle \sum _{i=0}^{n-1}x_{i}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<munderover>
<mo>∑<!-- ∑ --></mo>
<mrow class="MJX-TeXAtom-ORD">
<mi>i</mi>
<mo>=</mo>
<mn>0</mn>
</mrow>
<mrow class="MJX-TeXAtom-ORD">
<mi>n</mi>
<mo>−<!-- − --></mo>
<mn>1</mn>
</mrow>
</munderover>
<msub>
<mi>x</mi>
<mrow class="MJX-TeXAtom-ORD">
<mi>i</mi>
</mrow>
</msub>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle \sum _{i=0}^{n-1}x_{i}}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/a76abe3bdd8482aff0007672961fa1d5739e6de2.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -3.005ex; width:5.871ex; height:7.343ex;" alt="{\displaystyle \sum _{i=0}^{n-1}x_{i}}" loading="lazy"></span>.
</p><p><code>int <b>MPI_Reduce</b> (void *<i>sendbuf</i>, void *<i>recvbuf</i>, int <i>count</i>, MPI_Datatype <i>type</i>, MPI_Op <i>op</i>, int <i>root</i>, MPI_Comm <i>comm</i>)</code>
</p><p>Für den Parameter <code>op</code> existieren dabei folgende vordefinierte Reduktionsoperationen:
</p>
<div class="mw-heading mw-heading4"><h4 id="Logische_Operationen">Logische Operationen</h4></div>
<ul><li><code>MPI_LAND</code>: logische UND-Verknüpfung</li>
<li><code>MPI_BAND</code>: bitweise UND-Verknüpfung</li>
<li><code>MPI_LOR</code>: logische ODER-Verknüpfung</li>
<li><code>MPI_BOR</code>: bitweise ODER-Verknüpfung</li>
<li><code>MPI_LXOR</code>: logische exklusiv-ODER-Verknüpfung</li>
<li><code>MPI_BXOR</code>: bitweise exklusiv-ODER-Verknüpfung</li></ul>
<div class="mw-heading mw-heading4"><h4 id="Arithmetische_Operationen">Arithmetische Operationen</h4></div>
<ul><li><code>MPI_MAX</code>: Maximum</li>
<li><code>MPI_MIN</code>: Minimum</li>
<li><code>MPI_SUM</code>: Summe</li>
<li><code>MPI_PROD</code>: Produkt</li>
<li><code>MPI_MINLOC</code>: Minimum mit Prozess</li>
<li><code>MPI_MAXLOC</code>: Maximum mit Prozess</li></ul>
<p>Die Operationen <code>MPI_MINLOC</code> und <code>MPI_MAXLOC</code> geben zusätzlich den Rang des MPI-Prozesses zurück, der das Ergebnis bestimmte.
</p>
<div class="mw-heading mw-heading4"><h4 id="Benutzerdefinierte_Operationen">Benutzerdefinierte Operationen</h4></div>
<p>Zusätzlich zu den vordefinierten Reduktionsoperationen können auch eigene Reduktionsoperationen verwendet werden. Dazu wird eine frei programmierbare binäre Verknüpfungsoperation, die assoziativ sein muss und optional kommutativ sein kann, dem MPI bekanntgegeben:
</p><p><code>int <b>MPI_Op_create</b> (MPI_User_function *<i>function</i>, int <i>commute</i>, MPI_Op *<i>op</i>)</code>
</p><p>Die dazugehörige Nutzerfunktion berechnet aus zwei Eingabewerten einen Ausgabewert und macht dies – aus Optimierungsgründen – nicht nur einmal mit Skalaren, sondern elementweise auf Vektoren beliebiger Länge:
</p><p><code>typedef void <b>MPI_User_function</b> (void *invec, void *inoutvec, int *len, MPI_Datatype *datatype)</code>
</p>
<div class="mw-heading mw-heading4"><h4 id="Präfixreduzierung"><span id="Pr.C3.A4fixreduzierung"></span>Präfixreduzierung</h4></div>
<p>Zusätzlich zur oben genannten Akkumulation, existiert auch eine Allreduce Variante – welche das gleiche Ergebnis allen MPI-Prozessen zur Verfügung stellt und nicht nur einem <code>root</code> Prozess. Die sogenannte Präfixreduzierung erweitert nun diese Möglichkeit, indem nicht allen Prozessen das gleiche Ergebnis, sondern stattdessen ein prozessspezifisches Teilergebnis berechnet wird. Sei beispielsweise erneut <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle x_{i}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msub>
<mi>x</mi>
<mrow class="MJX-TeXAtom-ORD">
<mi>i</mi>
</mrow>
</msub>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle x_{i}}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/e87000dd6142b81d041896a30fe58f0c3acb2158.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.671ex; width:2.129ex; height:2.009ex;" alt="{\displaystyle x_{i}}" loading="lazy"></span> der Wert bei dem Prozess mit Rang <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle i}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>i</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle i}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/add78d8608ad86e54951b8c8bd6c8d8416533d20.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:0.802ex; height:2.176ex;" alt="{\displaystyle i}" loading="lazy"></span>, dann liefert Scan(+) die Partialsumme der Werte von Rang <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle 0}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mn>0</mn>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle 0}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/2aae8864a3c1fec9585261791a809ddec1489950.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.162ex; height:2.176ex;" alt="{\displaystyle 0}" loading="lazy"></span> bis <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle i}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>i</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle i}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/add78d8608ad86e54951b8c8bd6c8d8416533d20.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:0.802ex; height:2.176ex;" alt="{\displaystyle i}" loading="lazy"></span>: <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle \sum _{j=0}^{i}x_{j}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<munderover>
<mo>∑<!-- ∑ --></mo>
<mrow class="MJX-TeXAtom-ORD">
<mi>j</mi>
<mo>=</mo>
<mn>0</mn>
</mrow>
<mrow class="MJX-TeXAtom-ORD">
<mi>i</mi>
</mrow>
</munderover>
<msub>
<mi>x</mi>
<mrow class="MJX-TeXAtom-ORD">
<mi>j</mi>
</mrow>
</msub>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle \sum _{j=0}^{i}x_{j}}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/04d975f88e80b8392a855f82d4a406c0f5cc933c.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -3.338ex; width:5.981ex; height:7.509ex;" alt="{\displaystyle \sum _{j=0}^{i}x_{j}}" loading="lazy"></span>.
</p><p><code>int <b>MPI_Scan</b> (void *<i>sendbuf</i>, void *<i>recvbuf</i>, int <i>count</i>, MPI_Datatype <i>type</i>, MPI_Op <i>op</i>, MPI_Comm <i>comm</i>)</code>
</p><p>Soll der eigene Wert nicht mit in die Berechnung eingehen (d. h., ausgeschlossen werden), so kann dies mit der exklusiven Scan Funktion <code>MPI_Exscan</code> bewerkstelligt werden.
</p>
<div class="mw-heading mw-heading3"><h3 id="Allgather">Allgather</h3></div>
<p>Bei der <i>Allgather</i>-Operation schickt jeder Prozess an jeden anderen Prozess die gleichen Daten. Es handelt sich also um eine Multi-Broadcast-Operation, bei der es keinen gesonderten MPI-Prozess gibt.
</p><p><code>int <b>MPI_Allgather</b> (void *<i>sendbuf</i>, int <i>sendcount</i>, MPI_Datatype <i>sendtype</i>, void *<i>recvbuf</i>, int <i>recvcount</i>, MPI_Datatype <i>recvtype</i>, MPI_Comm <i>comm</i>)</code>
</p>
<div class="mw-heading mw-heading3"><h3 id="All-to-all_(Gesamtaustausch)"><span id="All-to-all_.28Gesamtaustausch.29"></span>All-to-all (Gesamtaustausch)</h3></div>
<p>Bei der All-to-all-Kommunikation werden – ähnlich wie bei der Allgather-Kommunikation – Daten zwischen allen Prozessen ausgetauscht. Dabei wird jedoch nur der <i>i</i>-te Teil des Sendebuffers an den <i>i</i>-ten Prozess gesendet. Daten, die vom Prozess mit dem Rang <i>j</i> kommen, werden entsprechend an <i>j</i>-ter Stelle im Empfangsbuffer gespeichert.
</p><p><code>int <b>MPI_Alltoall</b> (void *<i>sendbuf</i>, int <i>sendcount</i>, MPI_Datatype <i>sendtype</i>, void *<i>recvbuf</i>, int <i>recvcount</i>, MPI_Datatype <i>recvtype</i>, MPI_Comm <i>comm</i>)</code>
</p><p>Des Weiteren gibt es noch die synchronisierende <i>MPI_Barrier</i>-Operation. Diese Funktion kehrt erst zurück, nachdem alle in der angegebenen Gruppe befindlichen MPI-Prozesse diesen Teil des Programmes erreicht haben.
</p>
<div class="mw-heading mw-heading2"><h2 id="MPI-2">MPI-2</h2></div>
<p>Seit 1997 ist eine zweite Version des MPI-Standards verfügbar, die einige Erweiterungen zu dem weiterhin bestehenden MPI-1.1 Standard hinzufügt. Zu diesen Erweiterungen gehören unter anderem
</p>
<ul><li>eine dynamische Prozessverwaltung, d. h. Prozesse können nun zur Laufzeit erzeugt und gelöscht werden</li>
<li>[paralleler] Zugriff auf das Dateisystem</li></ul>
<ul><li>einseitige Kommunikation</li>
<li>Spezifikation zusätzlicher Sprachschnittstellen (C++, Fortran 90), wobei die Sprachschnittstellen zu C++ seit MPI 2.2 als veraltet markiert sind</li></ul>
<p>Beispiel: Lesen einer nx(n+1)-Matrix mit paralleler Datei-Eingabe und size Prozessen mit den Nummern rank = 0 … size-1. Die Spalte n+1 enthält die rechte Seite des Gleichungssystems A * x = b in Form der erweiterten Matrix [A, b]. Die Zeilen der Matrix werden gleichmäßig auf die Prozessoren verteilt. Die Verteilung erfolgt zyklisch (Jeder Prozessor eine Zeile, nach size Zeilen wird wieder rank=0 bedient) und nicht blockweise (jeder Prozessor bekommt einen zusammenhängenden Block von n/size Zeilen):
</p>
<pre> ndims = 1; /* dimensions */
aosi [0] = size * (n+1); /* array of sizes */
aoss [0] = n+1; /* array of subsizes */
aost [0] = rank * (n+1); /* array of starts */
order = MPI_ORDER_C; /* row or column order */
MPI_Type_create_subarray (ndims, aosi, aoss, aost, order, MPI_DOUBLE, &ft);
MPI_Type_commit (&ft);
</pre>
<pre> MPI_File_open (MPI_COMM_WORLD, fn, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
MPI_File_set_view (fh, sizeof (int), MPI_DOUBLE, ft, „native“, MPI_INFO_NULL);
</pre>
<pre> for (i = rank; i < n; i+=size)
{ MPI_File_read (fh, rdbuffer, n+1, MPI_DOUBLE, &status);
for (j = 0; j < n+1; j++)
{ A [i / size] [j] = rdbuffer [j]; /* nur die dem Prozess zugeordneten Zeilen */
} }
</pre>
<pre> MPI_File_close (&fh);
</pre>
<p>Die Schnittstelle folgt mit leichten der Parallelität geschuldeten Änderungen dem POSIX-1003.1-Standard. Die Datei wird mit MPI_File_open zum gemeinsamen Lesen eröffnet. Die Blenden (views) für die einzelnen Prozesse werden mit MPI_File_set_view festgelegt. Hier wird die vorher definierte Variable ft (filetype) benötigt, in der in einem Block von size * (n+1) doubles eine Zeile mit n+1 doubles herausgepickt wird, die bei Position rank * (n+1) beginnt. Somit wird vom gesamten Block jedem Prozess sukzessive genau eine Zeile zugewiesen. Dieser Typ wird mit MPI_Type_create_subarray definiert und mit MPI_Type_commit im MPI-System bekanntgemacht. Jeder Prozess liest mit MPI_File_read „seine“ Zeilen mit den Nummern i = rank, rank + size, rank + 2*size, … bis die gesamte Matrix gelesen wurden. Das Argument size of (int) berücksichtigt die Größe der Matrix, die am Anfang der Datei als int gespeichert wird.
</p><p>Gewinn: In size Prozessoren kann eine Matrix verteilt gespeichert werden, die auf einem einzelnen Prozessor in dessen Speicher keinen Platz mehr hätte. Das rechtfertigt auch die Konvention, als Speicher einer Parallelanlage die Summe des Speichers der Einzelcores und Einzelknoten anzugeben.
</p><p>Dateiformat:
</p>
<pre>n
Zeile 0 (n+1) Zahlen für Prozess rank 0
Zeile 1 (n+1) Zahlen für Prozess rank 1
…
Zeile r (n+1) Zahlen für Prozess rank r
…
Zeile size-1 (n+1) Zahlen für Prozess rank size-1
</pre>
<pre>Zeile size (n+1) Zahlen für Prozess rank 0
Zeile size+1 (n+1) Zahlen für Prozess rank 1
…
Zeile size+r (n+1) Zahlen für Prozess rank r
…
Zeile 2*size-1 (n+1) Zahlen für Prozess rank size-1
</pre>
<pre>Zeile 2*size (n+1) Zahlen für Prozess rank 0
…
…
es folgen entsprechend der Zeilenzahl der Matrix ausreichend viele solcher Blöcke
</pre>
<p>Das eigentliche Lesen erfolgt mit MPI_File_read. Jeder Prozess liest sequentiell nur die ihm zugeteilten Zeilen. Die kollektive Operation besteht darin, dass die MPI-Bibliothek das Lesen optimieren und parallelisieren kann. Nach Ende des Lesens muss die Datei wie üblich geschlossen werden. Das geschieht mit MPI_File_close. MPI verfügt für die Operationen über eigene Datentypen MPI_Datatype ft und MPI_File fh. Die Beschreibung des filetypes erfolgt mit normalen C-Variablen: int ndims;
int aosi [1];
int aoss [1];
int aost [1];
int order;
</p><p>Weiteres in.<sup id="cite_ref-MPI-2_4-0" class="reference"><a href="#cite_note-MPI-2-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="Implementierungen">Implementierungen</h2></div>
<div class="mw-heading mw-heading3"><h3 id="C++,_C_und_Fortran"><span id="C.2B.2B.2C_C_und_Fortran"></span>C++, C und Fortran</h3></div>
<p>Die erste Implementierung des MPI-1.x-Standards war <a href="Mpich" class="mw-redirect" title="Mpich">MPICH</a> vom <a href="Argonne_National_Laboratory" title="Argonne National Laboratory">Argonne National Laboratory</a> und der <a href="Mississippi_State_University" title="Mississippi State University">Mississippi State University</a>. Mittlerweile ist MPICH2 verfügbar, das den MPI-2.1-Standard implementiert. LAM/MPI vom Ohio Supercomputing Center war eine weitere freie Version, deren Weiterentwicklung inzwischen zugunsten von Open MPI eingestellt wurde.
</p><p>Ab der Version 1.35 der <a href="Boost_(C%2B%2B-Bibliothek)" title="Boost (C++-Bibliothek)">Boost Libraries</a> gibt es Boost.MPI, eine C++-freundliche Schnittstelle zu verschiedenen MPI-Implementierungen. Auch andere Projekte, wie z. B. TPO++, bieten diese Möglichkeit und sind in der Lage, STL-Container zu versenden und zu empfangen.
</p>
<div class="mw-heading mw-heading3"><h3 id="C#"><span id="C.23"></span>C#</h3></div>
<ul><li><a rel="nofollow" class="external text" href="http://osl.iu.edu/research/mpi.net/">MPI.NET</a> (MPI1)</li></ul>
<div class="mw-heading mw-heading3"><h3 id="Python">Python</h3></div>
<ul><li><a rel="nofollow" class="external text" href="https://mpi4py.github.io">MPI for Python</a> (MPI-1/MPI-2)</li>
<li><a rel="nofollow" class="external text" href="http://pympi.sourceforge.net/">pyMPI</a> (Entwicklung eingestellt)</li>
<li><a rel="nofollow" class="external text" href="http://mathema.tician.de/software/boostmpi">Boost:MPI Python Bindings</a> (Entwicklung eingestellt)</li></ul>
<div class="mw-heading mw-heading3"><h3 id="Java">Java</h3></div>
<ul><li><a rel="nofollow" class="external text" href="http://mpjexpress.org/">MPJ Express</a></li>
<li><a rel="nofollow" class="external text" href="http://www.hpjava.org/mpiJava.html">mpiJava</a> (MPI-1; Entwicklung eingestellt)</li></ul>
<div class="mw-heading mw-heading3"><h3 id="Perl">Perl</h3></div>
<ul><li><a rel="nofollow" class="external text" href="https://search.cpan.org/search?mode=all&query=mpi">einige MPI Module</a></li></ul>
<div class="mw-heading mw-heading3"><h3 id="R">R</h3></div>
<ul><li><a rel="nofollow" class="external text" href="http://www.stats.uwo.ca/faculty/yu/Rmpi/">Rmpi</a></li></ul>
<div class="mw-heading mw-heading3"><h3 id="Haskell">Haskell</h3></div>
<ul><li><a rel="nofollow" class="external text" href="http://www.foldr.org/~michaelw/hmpi/">hMPI</a></li>
<li><a rel="nofollow" class="external text" href="http://hackage.haskell.org/package/haskell-mpi">Haskell-MPI</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Siehe_auch">Siehe auch</h2></div>
<ul><li><a href="Parallele_Virtuelle_Maschine" title="Parallele Virtuelle Maschine">Parallele Virtuelle Maschine</a></li>
<li><a href="OpenMP" title="OpenMP">OpenMP</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Literatur">Literatur</h2></div>
<ul><li>Heiko Bauke, Stephan Mertens: <i>Cluster Computing.</i> Springer, 2006, ISBN 3-540-42299-4.</li>
<li>William Gropp, Ewing Lusk, Anthony Skjellum: <i>MPI – Eine Einführung – Portable parallele Programmierung mit dem Message-Passing Interface</i>. München 2007, ISBN 978-3-486-58068-6.</li>
<li>M. Firuziaan, O. Nommensen: <i>Parallel Processing via MPI & OpenMP</i>. Linux Enterprise, 10/2002</li>
<li><a href="Marc_Snir" title="Marc Snir">Marc Snir</a>, Steve Otto, Steven Huss-Lederman, David Walker, <a href="Jack_Dongarra" title="Jack Dongarra">Jack Dongarra</a>: <i>MPI – The complete reference</i>, Vol 1: The MPI core. 2. Auflage. MIT Press, 1998</li>
<li>William Gropp, Steven Huss-Lederman, Andrew Lumsdaine, Ewing Lusk, Bill Nitzberg, William Saphir, Marc Snir: <i>MPI-The Complete Reference.</i> Vol. 2: The MPI-2 Extensions. The MIT Press, 1998.</li></ul>
<div class="mw-heading mw-heading2"><h2 id="Weblinks">Weblinks</h2></div>
<ul><li><a rel="nofollow" class="external text" href="http://www-unix.mcs.anl.gov/mpi/">MPI</a></li>
<li><a rel="nofollow" class="external text" href="http://www.mpi-forum.org/">MPI-Forum</a></li>
<li><a rel="nofollow" class="external text" href="http://www.eurompi2010.org/">EuroMPI – MPI Users’ Group Meeting (2010 edition)</a></li>
<li><a rel="nofollow" class="external text" href="http://www.open-mpi.org/">Open MPI – frei verfügbare MPI Implementierung</a></li>
<li><a rel="nofollow" class="external text" href="http://phase.hpcc.jp/mirrors/mpi/mpich/index.html">MPICH – frei verfügbare MPI Implementierung</a></li>
<li><a rel="nofollow" class="external text" href="http://www-unix.mcs.anl.gov/mpi/mpich2/">MPICH2 – frei verfügbare MPI Implementierung</a></li>
<li><a rel="nofollow" class="external text" href="http://mvapich.cse.ohio-state.edu/">MVAPICH – MPI Implementierung mit VAPI</a></li>
<li><a rel="nofollow" class="external text" href="http://www.boost.org/">Boost</a></li>
<li><a rel="nofollow" class="external text" href="http://tpo.sourceforge.net/">TPO++</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Einzelnachweise">Einzelnachweise</h2></div>
<ol class="references">
<li id="cite_note-1"><span class="mw-cite-backlink"><a href="#cite_ref-1">↑</a></span> <span class="reference-text"><style data-mw-deduplicate="TemplateStyles:r261891140">
/* start https://de.wikipedia.org/ */
.mw-parser-output .webarchiv-memento a{color:inherit}
/* end https://de.wikipedia.org/ */
</style><a rel="nofollow" class="external text" href="https://web.archive.org/web/20061106152359/http://www.mpi-forum.org/docs/docs.html">MPI Documents</a> (<span class="webarchiv-memento"><a href="Webarchivierung#Begrifflichkeiten" title="Webarchivierung">Memento</a></span> des <style data-mw-deduplicate="TemplateStyles:r250917974">
/* start https://de.wikipedia.org/ */
.mw-parser-output .dewiki-iconexternal>a{background-position:center right!important;background-repeat:no-repeat!important}body.skin-minerva .mw-parser-output .dewiki-iconexternal>a{background-image:url("./_mw_/OOjs_UI_icon_external-link-ltr-progressive.svg")!important;background-size:10px!important;padding-right:13px!important}body.skin-timeless .mw-parser-output .dewiki-iconexternal>a,body.skin-monobook .mw-parser-output .dewiki-iconexternal>a{background-image:url("./_mw_/MediaWiki_external_link_icon.svg")!important;padding-right:13px!important}body.skin-vector .mw-parser-output .dewiki-iconexternal>a{background-image:url("./_mw_/Link.ernal-small-ltr-progressive.svg")!important;background-size:0.857em!important;padding-right:1em!important}
/* end https://de.wikipedia.org/ */
</style><span class="dewiki-iconexternal"><a class="external text" href="https://redirecter.toolforge.org/?url=http%3A%2F%2Fwww.mpi-forum.org%2Fdocs%2Fdocs.html">Originals</a></span> vom 6. November 2006 im <i><a href="Internet_Archive" title="Internet Archive">Internet Archive</a></i>) <small class="archiv-bot"><span class="wp_boppel noviewer" aria-hidden="true" role="presentation"><span typeof="mw:File"><span title="i"></span></span></span> <b>Info:</b> Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis.</small><span style="display:none"><a rel="nofollow" class="external text" href="http://IABotmemento.invalid/http://www.mpi-forum.org/docs/docs.html">@1</a></span><span style="display:none"><a rel="nofollow" class="external text" href="http://www.mpi-forum.org/docs/docs.html">@2</a></span><span style="display:none">Vorlage:Webachiv/IABot/www.mpi-forum.org</span></span>
</li>
<li id="cite_note-2"><span class="mw-cite-backlink"><a href="#cite_ref-2">↑</a></span> <span class="reference-text"><a rel="nofollow" class="external text" href="http://www.hpcadvisorycouncil.com/events/2012/Spain-Workshop/pres/3_OSU.pdf"><i>The Future of MPI</i>.</a> (PDF; 2,4 MB)</span>
</li>
<li id="cite_note-3"><span class="mw-cite-backlink"><a href="#cite_ref-3">↑</a></span> <span class="reference-text"><a rel="nofollow" class="external text" href="https://www.mpi-forum.org/docs/mpi-4.0/mpi40-report.pdf#subsection.B.1.2"><i>Changes in MPI-4.0</i></a></span>
</li>
<li id="cite_note-MPI-2-4"><span class="mw-cite-backlink"><a href="#cite_ref-MPI-2_4-0">↑</a></span> <span class="reference-text"><i><a rel="nofollow" class="external text" href="https://web.archive.org/web/20070921212101/http://www.mpi-forum.org/docs/mpi-20-html/mpi2-report.html">MPI-2: Extensions to the Message-Passing Interface</a> (<span class="webarchiv-memento"><a href="Webarchivierung#Begrifflichkeiten" title="Webarchivierung">Memento</a></span> des <span class="dewiki-iconexternal"><a class="external text" href="https://redirecter.toolforge.org/?url=http%3A%2F%2Fwww.mpi-forum.org%2Fdocs%2Fmpi-20-html%2Fmpi2-report.html">Originals</a></span> vom 21. September 2007 im </i><a href="Internet_Archive" title="Internet Archive">Internet Archive</a><i>) <small class="archiv-bot"><span class="wp_boppel noviewer" aria-hidden="true" role="presentation"><span typeof="mw:File"><span title="i"></span></span></span> <b>Info:</b> Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis.</small><span style="display:none"><a rel="nofollow" class="external text" href="http://IABotmemento.invalid/http://www.mpi-forum.org/docs/mpi-20-html/mpi2-report.html">@1</a></span><span style="display:none"><a rel="nofollow" class="external text" href="http://www.mpi-forum.org/docs/mpi-20-html/mpi2-report.html">@2</a></span><span style="display:none">Vorlage:Webachiv/IABot/www.mpi-forum.org</span></i></span>
</li>
</ol></div><!--htdig_noindex--><div><div class="zim-footer">
Dieser Artikel wurde von <a class="external text" title="Zuletzt bearbeitet am 2024-11-06" href="https://de.wikipedia.org/wiki/?title=Message_Passing_Interface&oldid=250110275">Wikipedia</a> herausgegeben. Der Text ist unter <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.de">Creative Commons Attribution-Share Alike 4.0</a> verfügbar, sofern nicht anders angegeben. Für die Mediendateien können zusätzliche Bedingungen gelten.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
<script src="./_webp_/webpHandler.js"></script>
</body></html>